
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <unistd.h>
#include <sys/socket.h>
#include <sys/sysinfo.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/wireless.h>
#include <fcntl.h>



#define SKIP_SPACE(p) while ((*p == ' ' || *p == '\t') && *p != '\0') { p++; }
#define SKIP_NONSPACE(p) while (*p != ' ' && *p != '\0') { p++; }

class SpeedInfo {
public:
    SpeedInfo() : bytes_in(0), bytes_out(0), last_up_time(0) {}
    void Renew(void) {
        struct  sysinfo         si;
        sysinfo(&si);
        int  time_diff = 0;
        if (last_up_time != 0) {
            time_diff = (int)si.uptime - last_up_time;
            if (time_diff <= 0) {
                return;
            }
        }
        last_up_time = (int)si.uptime;

        const char * dev = "wlan0";
        const char * path = "/proc/net/dev";

        struct stat buf;
        int ret = stat(path, &buf);
        if (ret == -1) {
            perror("stat");
            return;
        }

        int fd =  open(path, O_RDONLY);
        if (fd < 0) {
            perror("open");
            return;
        }
        int len = (int)buf.st_size;
        if (len == 0) {
            len = 81920;
        }
        char * buffer = (char *)malloc(len + 1);
        int total = 0;
        while (total < len) {
            len = read(fd, buffer + total, len - total);
            if (len <= 0) {
                perror("read");
                break;
            }
            total += len;
        }
        buffer[len - 1] = '\0';
        close(fd);

        char temp[1024];
        snprintf(temp, sizeof(temp), "%s:", dev);
        char * p = strstr(buffer, temp);
        if (!p) {
            printf("No such interface(%s).\n", dev);
            free(buffer);
            return;
        }
        p += strlen(temp);
        SKIP_SPACE(p);
        int in = atoi(p);
        int i;
        for (i=0; i<8; i++) {
            SKIP_NONSPACE(p);
            SKIP_SPACE(p);
        }
        if (*p == '\0') {
            printf("No Transmit info.\n");
            free(buffer);
            return;
        }
        int out = atoi(p);
        
        if (bytes_in == 0)
            bytes_in = in;
        if (bytes_out == 0)
            bytes_out = out;

        if (time_diff != 0) {
            rate_in = (in - bytes_in) / (float)time_diff;
            rate_out = (out - bytes_out) / (float)time_diff;
        }
        bytes_in = in;
        bytes_out = out;
    }

    float   rate_in;
    float   rate_out;
private:
    time_t  last_up_time;
    int     bytes_in;
    int     bytes_out;
};




// 获取网卡连接速度。
void PrintBitRate()
{
    const char * dev = "wlan0";

    int s = socket(AF_INET, SOCK_DGRAM, 0);
    if (s < 0) {
        perror("socket");
        return;
    }

    struct iwreq wrq;
    strncpy(wrq.ifr_name, dev, IFNAMSIZ);
    int ret = ioctl(s, SIOCGIWRATE, &wrq);
    if (ret < 0) {
        perror("ioctl.SIOCGIWRATE");
        close(s);
        return;
    }
    printf("%u\n", wrq.u.bitrate.value);
    close(s);
}


int main()
{
    PrintBitRate();

    SpeedInfo   si;
    while (true) {
        si.Renew();
        usleep(1000000);
        printf("%f in, %f out\n", si.rate_in, si.rate_out);
    }
    return 0;
}


